package com.goldsprite.microhorigame.screens.examples.spinegfsmexamples;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.g2d.PolygonSpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.esotericsoftware.spine.*;
import com.goldsprite.microhorigame.screens.examples.spinegfsmexamples.spinegfsm.SpineEntity;
import com.goldsprite.microhorigame.screens.examples.spinegfsmexamples.spinegfsm.SpineFsmInput;
import com.goldsprite.microhorigame.screens.examples.spinegfsmexamples.spinegfsm.SpineStateMachine;
import com.goldsprite.microhorigame.screens.examples.spinegfsmexamples.spinegfsm.states.SpineAttackState;
import com.goldsprite.microhorigame.screens.examples.spinegfsmexamples.spinegfsm.states.SpineIdleState;
import com.goldsprite.microhorigame.screens.examples.spinegfsmexamples.spinegfsm.states.SpineMoveState;
import com.goldsprite.microhorigame.screens.examples.spinegfsmexamples.spinegfsm.states.SpineMovingJumpState;

public class SpineCharacter {
	// Spine 核心组件
	private SkeletonRenderer renderer;
	private Skeleton skeleton;
	private AnimationState state;
	private TextureAtlas atlas;

	// 状态机系统
	private SpineStateMachine stateMachine;
	private SpineEntity spineEntity;
	private SpineFsmInput spineInput;

	// 配置和状态
	private CharacterConfig config;
	private int facingDirection = 1;
	private float deltaTime;

	public SpineCharacter(CharacterType characterType) {
		this.config = characterType.getConfig();
		this.spineInput = new SpineFsmInput();
	}

	public void create() {
		// 初始化 Spine 组件
		renderer = new SkeletonRenderer();
		renderer.setPremultipliedAlpha(true);

		atlas = new TextureAtlas(Gdx.files.internal(config.getAtlasPath()));
		SkeletonJson json = new SkeletonJson(atlas);
		json.setScale(config.scale);

		SkeletonData skeletonData = json.readSkeletonData(Gdx.files.internal(config.getJsonPath()));
		skeleton = new Skeleton(skeletonData);
		setFacingDirection(1);

		AnimationStateData stateData = new AnimationStateData(skeletonData);
		{
			stateData.setDefaultMix(0.1f);
			//移动转待机混合: 0.1秒
//			stateData.setMix(config.getAnimName(AnimType.MOVE), config.getAnimName(AnimType.IDLE), 0.1f);
		}
		state = new AnimationState(stateData);

		// 初始化状态机
		spineEntity = new SpineEntity(this, config);
		stateMachine = new SpineStateMachine(spineEntity, spineInput);

		// 注册状态
		stateMachine.registerState(new SpineIdleState(), 0);
		stateMachine.registerState(new SpineMoveState(), 1);
		stateMachine.registerState(new SpineMovingJumpState(), 2);
		stateMachine.registerState(new SpineAttackState(), 3);

		// 设置初始位置
		setPosition(Env.WORLD_WIDTH / 2, Env.WORLD_HEIGHT / 2);
		spineEntity.setPosition(Env.WORLD_WIDTH / 2, Env.WORLD_HEIGHT / 2);
	}

	public void update(float delta) {
		this.deltaTime = delta;

		// 处理输入
		handleInput();

		// 更新状态机
		stateMachine.update();

		// 更新 Spine 动画
		state.update(delta);
		state.apply(skeleton);
		skeleton.updateWorldTransform();
	}

	private void handleInput() {
		// 处理键盘输入
		boolean movingLeft = Gdx.input.isKeyPressed(Input.Keys.A);
		boolean movingRight = Gdx.input.isKeyPressed(Input.Keys.D);

		setMoveDirection(0);
		if (movingLeft) setMoveDirection(-1);
		else if (movingRight) setMoveDirection(1);
		else spineInput.setMoveProtect(false);

		if (Gdx.input.isKeyJustPressed(Input.Keys.J)) {
			spineInput.setAttacking(true);
		}
		if(!Gdx.input.isKeyPressed(Input.Keys.J) && spineInput.isAttacking()) {
//			spineInput.setAttacking(false);
		}

		if (Gdx.input.isKeyJustPressed(Input.Keys.K)) {
			spineInput.setJumping(true);
		}
		if(!Gdx.input.isKeyPressed(Input.Keys.K) && spineInput.isJumping()) {
			spineInput.setJumping(false);
		}
	}

	public void setMoveDirection(float direction) {
		spineInput.setMoveDirection(direction);
		spineEntity.updateFacing(direction);
	}

	// 被 SpineEntity 调用的方法
	public void setPosition(float x, float y) {
		skeleton.setPosition(x, y + config.yOffset);
	}

	public void setFacingDirection(int direction) {
		this.facingDirection = direction;
		skeleton.setScale(direction * config.scale, config.scale);
	}

	public void render(PolygonSpriteBatch batch) {
		batch.begin();
		renderer.draw(batch, skeleton);
		batch.end();
	}

	public void dispose() {
		if (atlas != null) atlas.dispose();
	}

	// Getter 方法
	public Skeleton getSkeleton() { return skeleton; }
	public AnimationState getAnimationState() { return state; }
	public CharacterConfig getConfig() { return config; }
	public float getDeltaTime() { return deltaTime; }

	public int getFacingDirection() {
		return (int) spineInput.getMoveDirection();
	}
}
